package com.reservation.service.impl;


import com.reservation.constant.JwtClaimsConstant;
import com.reservation.constant.MessageConstant;
import com.reservation.dto.auth.LoginDTO;
import com.reservation.dto.auth.RegisterDTO;
import com.reservation.entity.Users;
import com.reservation.exception.BaseException;
import com.reservation.mapper.AuthMapper;
import com.reservation.properties.JwtProperties;
import com.reservation.service.AuthService;
import com.reservation.utils.CurrentHolderUtil;
import com.reservation.utils.FileUploadUtil;
import com.reservation.utils.JwtUtil;
import com.reservation.utils.UrlUtil;
import com.reservation.vo.auth.LoginVO;
import com.reservation.vo.auth.UserInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 用户服务实现类
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {

    @Autowired
    private AuthMapper authMapper;


    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private FileUploadUtil fileUploadUtil;
    /**
     * 用户注册
     *
     * @param registerDTO 注册信息
     * @return 用户信息
     */
    @Override
    @Transactional // 添加事务注解
    public void register(RegisterDTO registerDTO) {

        //检查账号是否已存在且不是已删除状态
        Users existUser = authMapper.getByAccountAndRole(registerDTO.getAccount(), registerDTO.getRole());
        if (existUser != null) {
            // 如果账号存在但已被注销（status=3），允许重新注册
            if (existUser.getStatus() != 3) {
                throw new BaseException(MessageConstant.ACCOUNT_EXISTED);
            }
            // 账号已被注销，允许重新注册，记录日志
            log.info("检测到已注销账号正在重新注册: {}", registerDTO.getAccount());
        }

        //密码加密
        String encryptedPassword = DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes());        // 判断是新用户注册还是已注销用户重新注册
        if (existUser != null && existUser.getStatus() == 3) {
            // 已注销用户重新注册，更新用户信息
            existUser.setPasswordHash(encryptedPassword);
            existUser.setName(registerDTO.getName());
            existUser.setPhoneNumber(registerDTO.getPhone());
            existUser.setCompanyName(registerDTO.getCompany());
            existUser.setStatus(0); // 待审核
            existUser.setUpdateTime(LocalDateTime.now());

            log.info("更新已注销用户信息：{}", existUser);

            // 更新用户信息
            int rows = authMapper.updateUserInfo(existUser);
            if (rows > 0) {
                log.info("已注销用户重新注册成功，ID: {}", existUser.getId());
            } else {
                log.warn("已注销用户重新注册失败，ID: {}", existUser.getId());
                throw new BaseException("重新注册失败，请联系管理员");
            }
        } else {
            // 新用户注册
            Users user = Users.builder()
                    .account(registerDTO.getAccount())
                    .passwordHash(encryptedPassword)
                    .name(registerDTO.getName())
                    .phoneNumber(registerDTO.getPhone())
                    .role(registerDTO.getRole())
                    .companyName(registerDTO.getCompany())
                    .status(0)//待审核
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();

            log.info("注册新用户信息：{}", user);

            // 保存用户
            authMapper.insert(user);

            log.info("新用户插入成功，ID: {}", user.getId());
        }

    }

    /**
     * 用户登录
     *
     * @param loginDTO 登录信息
     * @return 登录结果(token + 用户信息)
     */    @Override
    public LoginVO login(LoginDTO loginDTO) {
        String secretKey = jwtProperties.getAuthSecretKey();
        log.info("secretKey: {}", secretKey);

        // 1. 根据账号及角色查询用户
        Users user = authMapper.getByAccountAndRole(loginDTO.getAccount(), loginDTO.getRole());
        if (user == null) {
            throw new BaseException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        // 2. 密码比对
        String encryptedPassword = DigestUtils.md5DigestAsHex(loginDTO.getPassword().getBytes());
        if (!encryptedPassword.equals(user.getPasswordHash())) {
            throw new BaseException(MessageConstant.PASSWORD_ERROR);
        }

        // 3. 检查账号状态
        // 账号状态为待审核
        if (user.getStatus() == 0) {
            throw new BaseException(MessageConstant.ACCOUNT_PENDING_APPROVAL);
        }

        // 账号状态为锁定
        if (user.getStatus() == 2) {
            throw new BaseException(MessageConstant.ACCOUNT_FROZEN);
        }

        // 账号状态为删除
        if (user.getStatus() == 3) {
            throw new BaseException(MessageConstant.ACCOUNT_DELETED);
        }

        // 4. 生成JWT令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.AUTH_ID, user.getId());
        claims.put(JwtClaimsConstant.AUTH_NAME, user.getName());
        claims.put(JwtClaimsConstant.AUTH_ROLE, user.getRole());
        String token = JwtUtil.createJWT(
                jwtProperties.getAuthSecretKey(),
                jwtProperties.getAuthTtl(),
                claims);

        log.info("生成的token: {}", token);

        return LoginVO.builder()
                .token(token)
                .build();
    }

    /**
     * 通过用户ID获取用户信息
     *
     * @param userId 用户ID
     * @return 用户信息
     */
    @Override
    public UserInfoVO getUserInfoById(Integer userId) {
        log.info("获取用户信息，用户ID: {}", userId);

        // 根据ID查询用户信息
        Users user = authMapper.getById(userId.longValue());

        if (user == null) {
            throw new BaseException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        // 检查账号状态
        if (user.getStatus() == 2|| user.getStatus() == 3) {
            throw new BaseException("账号状态异常，无法获取信息");
        }

        // 构建并返回用户信息VO
        return UserInfoVO.builder()
                .account(user.getAccount())
                .name(user.getName())
                .company(user.getCompanyName())
                .phone(user.getPhoneNumber())
                .avatarURL(UrlUtil.buildFullUrl(user.getAvatarURL()))
                .build();
    }


    @Transactional // 添加事务管理    @Override
    public String changeAvatar(MultipartFile file) {
        // 1. 获取当前登录用户ID
        Integer userId = CurrentHolderUtil.getCurrentId();
        if (userId == null) {
            throw new BaseException("无法获取当前用户信息，请重新登录");
        }

        // 2. 使用 FileUploadUtil 保存图片
        // 使用 userId 作为文件名的一部分，增加可读性
        String relativePath = fileUploadUtil.saveImage(file, userId);

        // 3. 更新数据库中的头像路径
        int updatedRows = authMapper.updateUserAvatar(userId, relativePath);
        if (updatedRows == 0) {
            log.warn("更新用户 {} 的头像失败，可能用户不存在", userId);
        } else {
            log.info("用户 {} 的头像更新成功，新路径: {}", userId, relativePath);
        }

        // 4. 返回新的头像访问路径（完整URL）
        return UrlUtil.buildFullUrl(relativePath);
    }    /**
     * 用户注销
     * @param userId 用户ID
     */
    @Override
    @Transactional // 添加事务注解
    public void logout(Integer userId) {
        log.info("用户注销，用户ID: {}", userId);

        // 从当前线程中移除用户信息
        CurrentHolderUtil.remove();

        // 将用户状态设为逻辑删除（状态值 3 表示已删除）
        int result = authMapper.updateUserStatus(userId, 3);
        if (result > 0) {
            log.info("用户 {} 状态已更新为已删除", userId);
        } else {
            log.warn("用户 {} 状态更新失败，可能用户不存在", userId);
            throw new BaseException("注销失败，用户不存在");
        }

        log.info("用户 {} 注销成功", userId);
    }
}